﻿using System.Collections.Generic;
using Microsoft.Xna.Framework;
using RaptorEngine.Components;
using RaptorEngine.Components.CollidableComponent;
using RaptorEngine.Threads;
using RaptorEngine.Components.Drawable;

namespace RaptorEngine
{
	public class Scene
	{

        internal int Id { get; private set; }

	    private bool _network;
        public bool Network { get; set; }

		// Used to not mess with the entityList that Render may be working on att the same time as Update
		public List<Entity> ToBeAdded { get; set; }
		public List<Entity> ToBeRemoved { get; set; }

	    private List<Entity> _entities;
        public List<Entity> Entities { get { return _entities; } }

        private Camera _camera;
        public Camera Camera {
            get { return _camera; }
            set 
            {
                _camera = value;
                value.Id = Id;
                GameEngine.Instance.Render.AddNewData(value);
            } 
        }
        public bool HasCamera
        { 
            get 
            { 
                if (_camera != null) return true; 
                else return false;
            } 
        }

        private bool _visible = false;
        public bool IsVisible
        { 
            get { return _visible; } 
            
            set 
            { 
                _visible = value;
 
                foreach (Entity e in _entities)
                {
                    if (e.HasComponent(ComponentType.Drawable2D))
                    {
                        Drawable2DComponent d = (Drawable2DComponent)e.GetComponent(ComponentType.Drawable2D);
                        d.Visible = _visible;
                    }
                    if (e.HasComponent(ComponentType.Drawable3D))
                    {
                        Drawable3DComponent d = (Drawable3DComponent)e.GetComponent(ComponentType.Drawable3D);
                        d.Visible = _visible;
                    }
                }
            } 
        }

        private bool _active = false;
        public bool IsActive { get { return _active; } set { _active = value; } }

        public Scene(bool network)
        {
            Id = GameEngine.Instance.GetNextId();
            _network = network;
			_entities = new List<Entity>();
			ToBeAdded = new List<Entity>();
			ToBeRemoved = new List<Entity>();
        }

		public void AddEntity(Entity e)
		{			
			ToBeAdded.Add(e); 	
		}
        
        // For network
        public Entity GetEntity(int entityID)
        {
            foreach (Entity entity in _entities)
            {
                if (entity.Id == entityID)
                    return entity;
            }
            return null;
        }

        // For network
        public List<Entity> GetNetworkableEntitys()
        {
            List<Entity> list = new List<Entity>();

            foreach (Entity entity in _entities)
            {
                if(entity.Networkable)
                    list.Add(entity);
            }
            return list;
        }

		/// <summary>
		/// Add the entity to a list that later will be removed to not mess up the Render thread
		/// </summary>
		/// <param name="e">The entity to later be removed</param>
		public void RemoveEntity(Entity e)
		{
			ToBeRemoved.Add(e);
		}

		/// <summary>
		/// Remove the entity when the update and the render thread are in sync
		/// </summary>
		/// <param name="e">The entity to be removed</param>
		public void RemoveEntityWhenInSync(Entity e)
		{
			e.Components.Clear();
			_entities.Remove(e);
			GameEngine.Instance.UpdateBuffer.Add(new ChangeMessage()
			{
				MessageType = ChangeMessageType.DeleteRenderData,
				ID = e.Id
			});
		}

        public List<Entity> GetDrawable2DEntities()
        {
            List<Entity> temp = new List<Entity>();
            
            foreach (Entity entity in _entities)
            {
                if(entity.Components.ContainsKey(ComponentType.Drawable2D))
                {
                    temp.Add(entity);
                }
            }

            return temp;
        }

        public List<Entity> GetDrawable3DEntities()
        {
            List<Entity> temp = new List<Entity>();

            foreach (Entity entity in _entities)
            {
                if (entity.Components.ContainsKey(ComponentType.Drawable3D))
                {
                    temp.Add(entity);
                }
            }

            return temp;
        }

	    public virtual void Initialize(){}

		internal List<Controllable> GetControllableComponents()
		{
			List<Controllable> controllables = new List<Controllable>();
			foreach (Entity entity in Entities)
			{
				if(entity.HasComponent(ComponentType.Controllable))
					controllables.Add((Controllable)entity.Components[ComponentType.Controllable]);
			}
			return controllables;
		}

		internal List<Movable> GetMoveableComponents()
		{
			List<Movable> movable = new List<Movable>();
			foreach (Entity entity in Entities)
			{
				if (entity.HasComponent(ComponentType.Movable))
					movable.Add((Movable)entity.Components[ComponentType.Movable]);
			}
			return movable;
		}

		internal List<Collidable> GetCollidableComponents()
		{
			List<Collidable> collidable = new List<Collidable>();
			foreach (Entity entity in Entities)
			{
				if (entity.HasComponent(ComponentType.Collidable))
					collidable.Add((Collidable)entity.Components[ComponentType.Collidable]);
			}
			return collidable;
		}

	    public virtual void Update()
	    {
			Camera.Update();
	    }

	}
}
